#! /usr/bin/env python
# -*- coding: utf8 -*-
from __future__ import with_statement

import pygtk
pygtk.require("2.0")

import gtk
import gps
import gnome
import thread
import gobject
import gtk.gdk
import gnome.ui

import sys

POSITION_MODE = 0
ALTITUDE_MODE = 1
UTCTIME_MODE  = 2

class gps_applet(object):
    __menu = """
        <popup name="button3">
            %s
            <separator name="Item1_5"                                                                                     />
            <menuitem  name="Item2" verb="goGoogleMaps" label="Go to _Google Maps"  pixtype="stock" pixname="gtk-jump-to" />
            <menuitem  name="Item3" verb="goYahooMaps"  label="Go to _Yahoo Maps"   pixtype="stock" pixname="gtk-jump-to" />
            <menuitem  name="Item4" verb="goWikiMapia"  label="Go to _WikiMapia"    pixtype="stock" pixname="gtk-jump-to" />
        </popup>
    """

    __trail_stopped_menu = '''
            <menuitem  name="Item0" verb="startTrail" label="_Start GPS trailing" pixtype="stock" pixname="gtk-media-record" />
            <placeholder name="Item1"                                                                                        />'''

    __trail_running_menu = '''
            <placeholder name="Item0"                                                                                        />
            <menuitem   name="Item1" verb="stopTrail" label="_Stop GPS trailing" pixtype="stock" pixname="gtk-media-stop"    />'''


    def __init__(self, applet, iid):
        self.__applet    = applet
        self.__label     = gtk.Label()
        self.__session   = gps.gps()
        self.__mode      = 0
        self.__prev_alt  = 10000000000.0
        self.__file      = None
        self.__file_lock = thread.allocate_lock()
        self.__gps_lock  = thread.allocate_lock()

        self.__trail = False


        self.__verbs = (("goGoogleMaps", self.goGoogleMaps), ("goYahooMaps", self.goYahooMaps), ("goWikiMapia", self.goWikiMapia),
                        ("startTrail", self.startTrail), ("stopTrail", self.stopTrail))

        self.__mode_lock = thread.allocate_lock()
        thread.start_new_thread(self.timer_callback, ())
        gobject.timeout_add(500, self.timer_callback)
        gobject.timeout_add(500, self.poll_gps)

        applet.add(self.__label)
        applet.connect("button-press-event", self.button_press)
        applet.setup_menu(self.__menu % self.__trail_stopped_menu, self.__verbs, None)

        applet.set_background_widget(applet)
        applet.show_all()

    def poll_gps(self):
        with self.__gps_lock:
            self.__session.query('admosy')
        return True

    def button_press(self, applet, event):
        if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
            with self.__mode_lock:
                self.__mode = (self.__mode + 1) % 3

    def timer_callback(self):
        self.__draw()
        return True

    # Trailing zone.
    def startTrail(self, event, data=None):
        buttons = (
                gtk.STOCK_SAVE,   gtk.RESPONSE_ACCEPT,
                gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL
        )
        dialog = gtk.FileChooserDialog("Choose trail file", None, gtk.FILE_CHOOSER_ACTION_SAVE, buttons)

        if dialog.run ()== gtk.RESPONSE_ACCEPT:
            self.__applet.setup_menu(self.__menu % self.__trail_running_menu, self.__verbs, None)
            with self.__file_lock:
                self.__file = open(dialog.get_filenames()[0], "w")
                self.__trail = True
            gobject.timeout_add(5000, self.save_trail)

        dialog.destroy()

    def stopTrail(self, event, data=None):
        with self.__file_lock:
            self.__file.close()
            self.__file = None
            self.__trail = False
            self.__applet.setup_menu(self.__menu % self.__trail_stopped_menu, self.__verbs, None)

    def save_trail(self):
        self.__gps_lock.acquire()
        with self.__file_lock:
            if self.__file != None:
                if self.__session.fix.latitude != 0.0 and self.__session.fix.longitude != 0.0:
                    if self.__session.fix.altitude != 10000000000.0:
                        self.__file.write("%s,%f,%f,%f\n" % (self.__session.utc, self.__session.fix.latitude, self.__session.fix.longitude, self.__session.fix.altitude))
                    else:
                        self.__file.write("%s,%f,%f,?\n" % (self.__session.utc, self.__session.fix.latitude, self.__session.fix.longitude))
                    self.__file.flush()

            retval = self.__trail
        self.__gps_lock.release()

        return retval

    # Jump-to websites zone
    def goGoogleMaps(self, event, data=None):
        data = {"lat": self.__session.fix.latitude, "lon" : self.__session.fix.longitude}
        url  = "http://maps.google.de/maps?f=q&hl=de&geocode=&q=%(lat)f,%(lon)f+(Me)&ie=UTF8&ll=%(lat)f,%(lon)f&spn=0.126775,0.32135&z=15&iwloc=addr&om=1" % data
        gnome.url_show(url)

    def goYahooMaps(self, event, data=None):
        data = {"lat": self.__session.fix.latitude, "lon" : self.__session.fix.longitude}
        url = "http://maps.yahoo.com/broadband#mvt=m&q1=%(lat)f%%2C+%(lon)f&trf=0&lon=%(lon)f&lat=%(lat)f&mag=3" % data
        gnome.url_show(url)

    def goWikiMapia(self, event, data=None):
        data = {"lat": self.__session.fix.latitude, "lon" : self.__session.fix.longitude}
        url = "http://wikimapia.org/#lat=%(lat)f&lon=%(lon)f&z=15&l=5&m=a&v=2" % data
        gnome.url_show(url)


    def __draw(self):
        if self.__session.fix.altitude != 10000000000.0:
            self.__prev_alt = self.__session.fix.altitude

        self.__gps_lock.acquire()
        with self.__mode_lock:
            if self.__mode == POSITION_MODE:
                lat = ""

                if self.__session.fix.latitude < 0:
                    lat = "%f S" % (-self.__session.fix.latitude,)
                else:
                    lat = "%f N" % (self.__session.fix.latitude,)

                lon = ""

                if self.__session.fix.longitude < 0:
                    lon = "%f W" % (-self.__session.fix.longitude,)
                else:
                    lon = "%f E" % (self.__session.fix.longitude,)

                label = "%s, %s" % (lat, lon)
            elif self.__mode == ALTITUDE_MODE:
                if self.__session.fix.altitude == 10000000000.0 and self.__prev_alt != self.__session.fix.altitude:
                    label = "%.2f m" % (self.__prev_alt,)
                elif self.__session.fix.altitude != 10000000000.0:
                    label = "%.2f m" % (self.__session.fix.altitude,)
                else:
                    label = "? m"
            elif self.__mode == UTCTIME_MODE:
                label = "%s" % (" ".join(self.__session.utc[:-4].split("T")), )


        self.__gps_lock.release()

        gtk.gdk.threads_enter()
        self.__label.set_text(label)
        gtk.gdk.threads_leave()
